home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 7 / PC World Interactive 7.iso / program / cprog.EXE / VIEW.C < prev    next >
C/C++ Source or Header  |  1995-10-02  |  24KB  |  1,031 lines

  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <sys\types.h>
  4. #include <sys\stat.h>
  5. #include <io.h>
  6. #include <share.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <dos.h>
  10. #include <share.h>
  11. #include <conio.h>
  12. #include <limits.h>
  13. #include <direct.h>
  14. #include "view.h"
  15.  
  16. /*
  17.   GLOBAL variable initialization 
  18. */
  19. VIEW *viewstack = NULL;                  /* pointer to the bottom view on screen */
  20.  
  21. UCHAR _far *screen;              /* pointer to display ram */
  22.  
  23. #if VIEW_HAS_MEMORY
  24.                                          /* huge 0 pointer to memory */
  25. UCHAR _huge *memory = (char _huge *)0;
  26. #endif
  27.                                          /* characters used in hex/dec conversion routines */
  28. UCHAR  hexdigits[] = {"0123456789ABCDEF"};
  29.  
  30. int view_offset   = 0;                   /* current offset into display memory */
  31. int view_attr     = 0;                   /* current display attribute */
  32. int view_is_mono  = FALSE;               /* flag indicates mono (TRUE) or color (FALSE) */
  33. int view_cols     = 80;
  34. int view_rows     = 25;
  35. UCHAR _far *bios_rows = (UCHAR _far *)0x00400084;
  36. UINT _far *bios_cols  = (UINT _far *)0x0040004A;
  37.  
  38. UCHAR *view_line   = NULL;                /* line input buffer */
  39.  
  40. #if VIEW_HAS_DIR
  41.  
  42. UCHAR *view_curdir = NULL;                /* current directory when view entered */
  43. UINT   view_curdrive = 0;
  44.  
  45. #endif
  46.  
  47. /*
  48.   Array of attributes for color and monochrome displays
  49. */
  50.  
  51. int view_attr_list[2][5] = {
  52.                              {     /* Color Attributes */
  53.                              0x1f, /* Active Window */
  54.                              0x30, /* Inactive Window */
  55.                              0x4f, /* Error Message */
  56.                              0x1b, /* Get a String  */
  57.                              0x31  /* Get a String Cursor */
  58.                              }, 
  59.                              {     /* Mono Attributes */
  60.                              0x0f, /* Active Window */
  61.                              0x70, /* Inactive Window */
  62.                              0x0f, /* Error Message */
  63.                              0x01, /* Get a String  */
  64.                              0x70  /* Get a String Cursor */
  65.                              }
  66.                            };
  67.  
  68. /*
  69.  
  70.    Function: main( int argc, UCHAR *argv[] )
  71.  
  72.    Description: 
  73.      This function will :
  74.  
  75.      1) close any "extra" file handles we inherited from
  76.      whoever ran us to give us more views
  77.  
  78.      2) save the current directory
  79.  
  80.      3) figure out whether we're in color or monochrome and set the
  81.      video buffer address in screen
  82.  
  83.      4) check the standard input to see if it's a file and
  84.      if so add it to the list of views and open a new standard
  85.      input.
  86.  
  87.      5) if we have no command line arguments prompt for file name
  88.  
  89.      6) process all command line arguments as if they were file names
  90.  
  91.      7) go into the view user interface and view files
  92.  
  93.      8) if we exit this way restore current directory
  94. */
  95.  
  96. main( int argc, UCHAR *argv[] )
  97. {
  98.   int i;
  99.   char fname[15];
  100.  
  101.   _harderr(view_errfunc);
  102.                                          /* Close "extra" file handles */
  103.   _dos_close(fileno(stderr));
  104.   _dos_close(fileno(stdaux));
  105.   _dos_close(fileno(stdprn));
  106.   _dos_close(fileno(stdout));
  107.                                          /* Assume :) that video mode 7 is monochrome */
  108.   if (view_getvidmode() == 7)
  109.     {
  110.     view_is_mono = TRUE;
  111.     screen = (UCHAR _far *)0xB0000000;
  112.     }
  113.   else
  114.     {
  115.     view_is_mono = FALSE;
  116.     screen = (UCHAR _far *)0xB8000000;
  117.     }
  118.  
  119.   view_rows = (*bios_rows)+1;
  120.   view_cols = (*bios_cols);
  121.                                          /* Save the current directory */
  122. #if VIEW_HAS_DIR
  123.   _dos_getdrive(&view_curdrive);
  124.   view_curdir = getcwd(NULL,80);
  125.   if (!view_curdir)
  126.     view_error(1,"VIEW0001");
  127. #endif
  128.                                          /* If stdin is a file then add it */
  129.   if (!isatty(fileno(stdin))) 
  130.     view_new(NULL,0,0,16,45);
  131.                                          /* If no args prompt for file */
  132.   if (argc <= 1 && !viewstack )
  133.     {
  134. #if VIEW_HAS_NEWFILE
  135.     view_newfile();
  136. #else
  137.     view_error(1,"[command |]VIEW [<filename] [filename .. filenameN]");
  138. #endif
  139.     }
  140.   else                                   /* process args as file names */
  141.     {
  142.     for (i = 1; i < argc; i ++)
  143.       view_new(argv[i],0,0,16,45);
  144.     }
  145.                                          /* put it on the screen and play */
  146.                                          /* with it */
  147.   view();
  148.  
  149. #if VIEW_HAS_DIR
  150.   if (view_curdir)                       /* return to saved dir and release memory */
  151.     {
  152.     _dos_setdrive(view_curdrive,&i);
  153.     chdir(view_curdir);
  154.     free(view_curdir);
  155.     }
  156. #endif
  157. }
  158. /*
  159.    Function: void view(void)
  160.  
  161.    Description:
  162.      This function puts up the user interface for view and accepts the
  163.      users input. It is basically a big switch on what key they hit. The
  164.      keys break down into extended and regular, extended keys are always
  165.      preceded by a null scan code.
  166.  
  167.      There are a set of offsets row_offset,col_offset etc... these are
  168.      set when certain keys are hit and are added to their corresponding
  169.      fields. The view_refresh routine enforces all dimensional constraints
  170.      so we don't worry about "overflow" or "underflow" in this routine.
  171.  
  172.      If page_offset is set to a non-zero value then the file is read 
  173.      either forwards or backwards abs(page_offset) times.
  174.  
  175.      The different refresh modes are used to speed up the screen update
  176.      when only the top window needs to be updated or only the top window's
  177.      contents.
  178. */
  179. void view(void)
  180. {
  181.   int c1;                                /* first character read */
  182.   int c2;                                /* second character read */
  183.   int row_offset;                        /* change row of window */
  184.   int col_offset;                        /* change col of window */
  185.   int height_offset;                     /* change height of window */
  186.   int width_offset;                      /* change width of window */
  187.   int line_offset;                       /* change coff of window */
  188.   int page_offset;                       /* change page of contents of window */
  189.   int refresh_mode;                      /* see refresh modes in view.h */
  190.   VIEW *top;                             /* temporary ptr to top window */
  191.  
  192.   if (!viewstack) return;                /* there aren't any views so return */
  193.  
  194.   if (!view_line)                        /* allocate the line buffer if NULL */
  195.     {
  196.     if (!(view_line = malloc(VIEW_MAX_LINE+1)))
  197.       view_error(1,"VIEW0002");
  198.     }
  199.  
  200.   view_tile();                           /* arrange the windows nicely */
  201.   top = viewstack;
  202.   do
  203.     {
  204.     view_scroll(top,SCROLL_RESET);
  205.     top = top->next;
  206.     }
  207.   while( top != viewstack );
  208.  
  209.   view_refresh(REFRESH_ALL);             /* put them on the screen */
  210.  
  211.  
  212.   for(;;)
  213.     {
  214.     refresh_mode = REFRESH_ALL;          /* reset change variables */
  215.     row_offset   = 0;
  216.     col_offset   = 0;
  217.     height_offset= 0;
  218.     width_offset = 0;
  219.     line_offset  = 0;
  220.     page_offset  = SCROLL_NONE;
  221.  
  222.     c1 = getch();                        /* get a keystroke from console */
  223.     
  224.     switch( c1 )                         /* select an action based on key */
  225.       {
  226.       case 0:                            /* an extended key follows */
  227.         c2 = getch();                    /* get extended keysroke */
  228.  
  229.         switch(c2)
  230.           {
  231.           case CURSOR_DOWN:
  232.             refresh_mode = REFRESH_CONTENTS;
  233.             page_offset = SCROLL_DOWN;
  234.           break;
  235.  
  236.           case CURSOR_LEFT:
  237.             refresh_mode = REFRESH_CONTENTS;
  238.             line_offset = -3;
  239.           break;
  240.  
  241.           case CURSOR_RIGHT:
  242.             refresh_mode = REFRESH_CONTENTS;
  243.             line_offset = 3;
  244.           break;
  245.  
  246.           case CURSOR_UP:
  247.             refresh_mode = REFRESH_CONTENTS;
  248.             page_offset = SCROLL_UP;
  249.           break;
  250.  
  251.           case CNTL_CURSOR_LEFT:
  252.             refresh_mode = REFRESH_TOP;
  253.             col_offset = -3;
  254.           break;
  255.  
  256.           case CNTL_CURSOR_RIGHT:
  257.             refresh_mode = REFRESH_TOP;
  258.             col_offset = 3;
  259.           break;
  260.  
  261.           case CNTL_PGUP:
  262.             refresh_mode = REFRESH_TOP;
  263.             row_offset = -1;
  264.           break;
  265.  
  266.           case CNTL_PGDN:
  267.             refresh_mode = REFRESH_TOP;
  268.             row_offset = 1;
  269.           break;
  270.  
  271.           case CNTL_HOME:
  272.             view_tile();
  273.             height_offset = view_rows;
  274.             width_offset = view_cols;
  275.           break;
  276.  
  277.           case CNTL_END:
  278.             view_tile();
  279.           break;
  280.  
  281.           case PGDN:
  282.             refresh_mode = REFRESH_CONTENTS;
  283.             page_offset = SCROLL_PAGE_DOWN;
  284.           break;
  285.  
  286.           case PGUP:
  287.             refresh_mode = REFRESH_CONTENTS;
  288.             page_offset = SCROLL_PAGE_UP;
  289.           break;
  290.  
  291.           case HOME:
  292.             refresh_mode = REFRESH_CONTENTS;
  293.             page_offset  = SCROLL_HOME;
  294.           break;
  295.  
  296.           case END:
  297.             refresh_mode = REFRESH_CONTENTS;
  298.             page_offset  = SCROLL_END;
  299.           break;
  300.  
  301.           case SHIFT_TAB:
  302.             view_refresh(REFRESH_PREV);
  303.             page_offset  = SCROLL_RESET;
  304.           break;
  305.  
  306.           default:
  307.           continue;
  308.           }
  309.       break;
  310.  
  311.       case 'e':
  312.       case 'E':
  313.          view_refresh(REFRESH_OFF);
  314.  
  315.          if (view_rows < 43)
  316.            {
  317.            _asm
  318.               {
  319.               push es
  320.               mov  ax,40H
  321.               mov  es,ax
  322.               push es:[87H]
  323.               or   byte ptr es:[87H],1
  324.  
  325.               mov  ax,1112H
  326.               xor  bx,bx
  327.               int  10h
  328.  
  329.               pop  es:[87H]
  330.               pop  es
  331.  
  332.               mov  ax,1200H
  333.               mov  bx,0020H
  334.               int  10h
  335.               }
  336.             }
  337.           else
  338.             {
  339.             _asm
  340.                {
  341.                push es
  342.                mov  ax,40H
  343.                mov  es,ax
  344.                push es:[87H]
  345.                or   byte ptr es:[87H],1
  346.  
  347.                mov ax,1111H
  348.                xor bx,bx
  349.                int 10h
  350.  
  351.                pop  es:[87H]
  352.                pop  es
  353.                }
  354.             }
  355.  
  356.          view_rows = (*bios_rows)+1;
  357.          view_cols = (*bios_cols);
  358.          view_tile();
  359.          refresh_mode = REFRESH_ALL;
  360.       break;
  361.  
  362.  
  363.       case 'w':
  364.         refresh_mode = REFRESH_TOP;
  365.         width_offset = -3;
  366.       break;
  367.  
  368.       case 'W':
  369.         refresh_mode = REFRESH_TOP;
  370.         width_offset = 3;
  371.       break;
  372.  
  373.       case 'h':
  374.         refresh_mode = REFRESH_TOP;
  375.         height_offset = -3;
  376.       break;
  377.  
  378.       case 'H':
  379.         refresh_mode = REFRESH_TOP;
  380.         height_offset = 3;
  381.       break;
  382.  
  383.       case 'C':
  384.       case 'c':
  385.         view_new(viewstack->prev->vf->fname,viewstack->prev->row,viewstack->prev->col,viewstack->prev->rows,viewstack->prev->cols);
  386.         view_tile();
  387.         page_offset  = SCROLL_RESET;
  388.       break;
  389.  
  390. #if VIEW_HAS_GOTO
  391.       case 'g':
  392.       case 'G':
  393.         refresh_mode = REFRESH_CONTENTS;
  394.         page_offset  = SCROLL_RESET;
  395.         view_goto_line();
  396.       break;
  397. #endif
  398.  
  399. #if VIEW_HAS_SEARCH
  400.       case 'S':
  401.       case 's':
  402.         refresh_mode = REFRESH_CONTENTS;
  403.         page_offset  = SCROLL_RESET;
  404.         view_search();
  405.       break;
  406. #endif
  407.  
  408.  
  409. #if VIEW_HAS_NEWFILE
  410.       case 'F':
  411.       case 'f':
  412.         if (!view_newfile()) continue;
  413.         view_tile();
  414.         page_offset = SCROLL_RESET;
  415.       break;
  416. #endif
  417.  
  418.       case 'D':
  419.       case 'd':
  420.         view_delete();
  421.         view_tile();
  422.       break;
  423.  
  424. #if VIEW_HAS_RAW
  425.       case 'X':
  426.       case 'x':
  427.         viewstack->prev->vf->lmode = VIEW_HEX_MODE;
  428.         page_offset = SCROLL_RESET;
  429.       break;
  430.  
  431.       case 'B':
  432.       case 'b':
  433.         viewstack->prev->vf->lmode = VIEW_BIN_MODE;
  434.         page_offset = SCROLL_RESET;
  435.       break;
  436. #endif
  437.  
  438.       case TAB:
  439.         view_refresh(REFRESH_NEXT);
  440.         page_offset  = SCROLL_RESET;
  441.       break;
  442.  
  443.       case ESC:
  444.         view_quit();
  445.       break;
  446.  
  447.       default:
  448.       continue;
  449.       }
  450.  
  451.     top       = viewstack->prev;
  452.     top->row  += row_offset;
  453.     top->col  += col_offset;
  454.     top->coff += line_offset;
  455.     top->rows += height_offset;
  456.     top->cols += width_offset;
  457.  
  458.     view_scroll(top,page_offset);
  459.     view_refresh(refresh_mode);
  460.     }
  461.  
  462. void view_scroll( VIEW *current, int mode )
  463. {
  464.    int      i;
  465.    VIEWFILE *vf;
  466.    ULONG    *pos;
  467.    UCHAR    **lines;
  468.  
  469.    if (kbhit())
  470.      if (!getch()) getch();
  471.  
  472.    vf    = current->vf;
  473.    pos   = current->pos;
  474.    lines = current->lines;
  475.  
  476.    switch( mode )
  477.      {
  478.      case SCROLL_NONE     :
  479.      return;
  480.  
  481.      case SCROLL_DOWN     :
  482.        if (lines[0])
  483.          {
  484.          view_seek(vf,pos[(VIEW_LINE_VIEW-1)],SEEK_SET);
  485.          view_getl_fwd(vf,view_line,VIEW_MAX_LINE);
  486.  
  487.          memmove(pos,pos+1,(VIEW_LINE_VIEW-1)*sizeof(ULONG));
  488.  
  489.          if (lines[0]) free(lines[0]);
  490.  
  491.          memmove(lines,lines+1,(VIEW_LINE_VIEW-1)*sizeof(UCHAR *));
  492.  
  493.          pos[(VIEW_LINE_VIEW-1)] = view_tell(vf);
  494.  
  495.          if (!view_getl_fwd(vf,view_line,VIEW_MAX_LINE))
  496.            lines[(VIEW_LINE_VIEW-1)] = view_strdup(view_line);
  497.          else
  498.            {
  499.            lines[(VIEW_LINE_VIEW-1)] = NULL;
  500.            pos[(VIEW_LINE_VIEW-1)]   = LONG_MAX;
  501.            }
  502.          }
  503.      break;
  504.  
  505.  
  506.      case SCROLL_UP       :
  507.        if (pos[0])
  508.          {
  509.          view_seek(vf,pos[0],SEEK_SET);
  510.  
  511.          memmove(pos+1,pos,(VIEW_LINE_VIEW-1)*sizeof(ULONG));
  512.  
  513.          if (lines[(VIEW_LINE_VIEW-1)]) free(lines[(VIEW_LINE_VIEW-1)]);
  514.                     
  515.          memmove(lines+1,lines,(VIEW_LINE_VIEW-1)*sizeof(UCHAR *));
  516.  
  517.          view_getl_bwd(vf,view_line,VIEW_MAX_LINE);
  518.  
  519.          pos[0] = view_tell(vf);
  520.  
  521.          view_getl_fwd(vf,view_line,VIEW_MAX_LINE);
  522.  
  523.          lines[0] = view_strdup(view_line);
  524.          }
  525.      break;
  526.  
  527.      case SCROLL_PAGE_UP  :
  528.        for (i = 0; i < (current->rows-2); i++)
  529.          view_scroll(current,SCROLL_UP);
  530.      break;
  531.  
  532.      case SCROLL_PAGE_DOWN:
  533.        for (i = 0; i < (current->rows-2); i++)
  534.          view_scroll(current,SCROLL_DOWN);
  535.      break;
  536.  
  537.      case SCROLL_HOME     :
  538.        view_seek(vf,0L,SEEK_SET);
  539.        view_scroll(current,SCROLL_RESET);
  540.      break;
  541.  
  542.      case SCROLL_END      :
  543.        view_seek(vf,0L,SEEK_END);
  544.        view_scroll(current,SCROLL_RESET);
  545.        view_scroll(current,SCROLL_PAGE_UP);
  546.      break;
  547.  
  548.      case SCROLL_CLEAR    :
  549.        for (i = 0; i < VIEW_LINE_VIEW; i ++)
  550.          {
  551.          pos[i] = LONG_MAX;
  552.          if (lines[i])
  553.            {
  554.            free(lines[i]);
  555.            lines[i] = NULL;
  556.            }
  557.          }
  558.  
  559.        return;
  560.      break;
  561.  
  562.      case SCROLL_RESET    :
  563.  
  564.        view_scroll(current,SCROLL_CLEAR);
  565.  
  566.        for (i = 0; i < VIEW_LINE_VIEW; i ++ )
  567.          {
  568.          pos[i] = view_tell(vf);
  569.          if (!view_getl_fwd(vf,view_line,VIEW_MAX_LINE))
  570.            lines[i] = view_strdup(view_line);
  571.          else
  572.            break;
  573.          }
  574.      break;
  575.      }
  576.  
  577.   view_seek(vf,pos[0],SEEK_SET);
  578. }
  579.  
  580.  
  581. void view_new( UCHAR *fname, int row,int col,int rows,int cols )
  582. {
  583.   VIEW *new;
  584.   int th;
  585.  
  586.   if (!strcmp(fname,"Standard Input")) return;
  587.  
  588.   new = (VIEW *)malloc(sizeof(VIEW));
  589.   if (!new) view_error(1,"VIEW0003");
  590.  
  591.   if (!(new->vf = view_open(fname)))
  592.     {
  593.     free(new);
  594.     return;
  595.     }
  596.  
  597.   new->row  = row;
  598.   new->col  = col;
  599.   new->rows = rows;
  600.   new->cols = cols;
  601.   memset(new->pos,'\0',VIEW_LINE_VIEW*sizeof(ULONG));
  602.   memset(new->lines,'\0',VIEW_LINE_VIEW*sizeof(UCHAR *));
  603.   new->coff = 0;
  604.   new->save = NULL;
  605.  
  606.  
  607.   if (viewstack == NULL)
  608.     {
  609.     new->next = new;
  610.     new->prev = new;
  611.     viewstack = new;
  612.     }
  613.   else
  614.     {
  615.     new->next = viewstack;
  616.     new->prev = viewstack->prev;
  617.     viewstack->prev->next = new;
  618.     viewstack->prev = new;
  619.     }
  620. }
  621.  
  622. void view_restore( VIEW *trav )
  623. {
  624.    view_putsave(trav->save);
  625.    trav->save = NULL;
  626. }
  627.  
  628. void view_save( VIEW *trav )
  629. {
  630.    trav->save = view_getsave(trav->row,trav->col,trav->rows,trav->cols);
  631. }
  632.  
  633. void view_refresh(int refresh_mode)
  634. {
  635.    VIEW *trav;
  636.    int  r;
  637.    int  blank;
  638.    UCHAR _far *oscreen;
  639.  
  640.    if (refresh_mode != REFRESH_CONTENTS && refresh_mode != REFRESH_TOP)
  641.      {
  642.      oscreen = screen;
  643.  
  644.      screen = malloc(view_rows*(view_cols*2));
  645.      if (!screen)
  646.        {
  647.        screen = oscreen;
  648.        }
  649.      else
  650.        {
  651.        memmove(screen,oscreen,view_rows*(view_cols*2));
  652.        }
  653.      }
  654.  
  655.    if (refresh_mode != REFRESH_CONTENTS)
  656.      {
  657.      trav = viewstack->prev;
  658.  
  659.      do
  660.        {
  661.        if (trav->save)
  662.          view_restore(trav);
  663.      
  664.        trav = trav->prev;
  665.  
  666.        if (refresh_mode == REFRESH_CONTENTS || refresh_mode == REFRESH_TOP) break;
  667.        }
  668.      while(trav != viewstack->prev);
  669.      }
  670.  
  671.    if (refresh_mode == REFRESH_NEXT)
  672.      {
  673.      viewstack = viewstack->next;
  674.      refresh_mode = REFRESH_ALL;
  675.      }
  676.  
  677.    if (refresh_mode == REFRESH_PREV)
  678.      {
  679.      viewstack = viewstack->prev;
  680.      refresh_mode = REFRESH_ALL;
  681.      }
  682.  
  683.    if (refresh_mode != REFRESH_OFF) 
  684.      {
  685.      if (refresh_mode != REFRESH_ALL)
  686.        trav = viewstack->prev;
  687.      else
  688.        trav = viewstack;
  689.  
  690.      do 
  691.        {
  692.        if (trav == viewstack->prev)
  693.          view_attr = ACTIVE_WINDOW;
  694.        else
  695.          view_attr = INACTIVE_WINDOW;
  696.  
  697.        trav->rows = max(trav->rows,3);
  698.        trav->rows = min(trav->rows,view_rows);
  699.        trav->cols = max(trav->cols,3);
  700.        trav->cols = min(trav->cols,view_cols);
  701.  
  702.        trav->col  = max(trav->col,0);
  703.        trav->col  = min(trav->col,view_cols-trav->cols);
  704.  
  705.        trav->row  = max(trav->row,0);
  706.        trav->row  = min(trav->row,view_rows-trav->rows);
  707.                                
  708.        trav->coff = max(trav->coff,0);
  709.  
  710.        if (refresh_mode != REFRESH_CONTENTS)
  711.          {
  712.          view_save(trav);
  713.          view_frame(trav->vf->fname,trav->row,trav->col,trav->rows,trav->cols);
  714.          }
  715.  
  716.        for (r = 1; r < trav->rows-1; r ++)
  717.          {
  718.          blank = TRUE;
  719.          view_goto(trav->row+r,trav->col+1);
  720.  
  721.          if (trav->lines[r-1] && (strlen(trav->lines[r-1]) > trav->coff))
  722.            {
  723.            view_puts(trav->lines[r-1]+trav->coff,trav->cols-2);
  724.            blank = FALSE;
  725.            }
  726.  
  727.          if (blank) view_fill(' ',trav->cols-2);
  728.          }
  729.  
  730.        trav = trav->next;
  731.  
  732.        if (refresh_mode != REFRESH_ALL) break;
  733.        } 
  734.      while(trav != viewstack);
  735.      }
  736.  
  737.    if (refresh_mode == REFRESH_ALL || refresh_mode == REFRESH_OFF)
  738.      {
  739.      if (screen != oscreen)
  740.        {
  741.        memmove(oscreen,screen,view_rows*(view_cols*2));
  742.        free(screen);
  743.        screen = oscreen;
  744.        }
  745.      }
  746. }
  747.  
  748. void view_quit( void )
  749. {
  750.   for(;;) view_delete();
  751. }
  752.  
  753. void view_tile( void )
  754. {
  755. #if VIEW_HAS_TILE
  756.  
  757.   VIEW *trav;
  758.   int windows;
  759.   int vsize,hsize;
  760.   int row,col;
  761.  
  762.   if (!viewstack) return;
  763.  
  764.   windows = 0;
  765.   trav    = viewstack;
  766.  
  767.   do
  768.     {
  769.     windows ++;
  770.     trav = trav->next;
  771.     }
  772.   while (trav != viewstack);
  773.  
  774.   hsize = view_cols;
  775.   vsize = view_rows;
  776.  
  777.   while ( (view_cols/hsize)*(view_rows/vsize) < windows )
  778.     vsize --;
  779.  
  780.   if (vsize < 3)
  781.     {
  782.     vsize = view_rows;
  783.     while ( (view_cols/hsize)*(view_rows/vsize) < windows )
  784.       hsize --;
  785.     }
  786.  
  787.   if (hsize < 10)
  788.     {
  789.     hsize = view_cols;
  790.     vsize = 24;
  791.  
  792.     while ( (view_cols/hsize)*(view_rows/vsize) < windows )
  793.       {
  794.       hsize -= 3;
  795.       vsize --;
  796.       }
  797.     }
  798.     
  799.   trav = viewstack;
  800.   row  = 0;
  801.   col  = 0;
  802.  
  803.   do
  804.     {
  805.     trav->row = row;
  806.     trav->col = col;
  807.     trav->rows = vsize;
  808.     trav->cols = hsize;
  809.  
  810.     col += hsize;
  811.     if (col+hsize > view_cols)
  812.       {
  813.       col = 0;
  814.       row += vsize;
  815.       }
  816.     trav = trav->next;
  817.     }
  818.   while(trav != viewstack);
  819.  
  820. #endif /* VIEW_HAS_TILE */
  821. }
  822.   
  823. void view_delete( void )
  824. {
  825.    VIEW *hold;
  826.    int lets_exit = FALSE;
  827.    
  828.  
  829.    if (viewstack->prev == viewstack)
  830.      lets_exit = TRUE;
  831.  
  832.    hold = viewstack->prev;
  833.    viewstack->prev->prev->next = viewstack;
  834.    viewstack->prev = viewstack->prev->prev;
  835.    view_restore(hold);
  836.    view_scroll(hold,SCROLL_CLEAR);
  837.    view_close(hold->vf);
  838.    free(hold);
  839.  
  840.    if (lets_exit) 
  841.      {
  842.      if (view_line) free(view_line);
  843.  
  844. #if VIEW_HAS_DIR
  845.      if (view_curdir)
  846.        {
  847.        _dos_setdrive(view_curdrive,&lets_exit);
  848.        chdir(view_curdir);
  849.        free(view_curdir);
  850.        }
  851. #endif
  852.      exit(0);
  853.      }
  854. }
  855.  
  856. #if VIEW_HAS_NEWFILE
  857. int view_newfile( void )
  858. {
  859.   int c1,c2;
  860.   char fname[80];
  861.  
  862.   fname[0] = '\0';
  863.  
  864.   do
  865.     {
  866.     c1 = view_prompt("New File","Filename:",fname,40);
  867.  
  868. #if VIEW_HAS_DIR
  869.     if (c1 && !strlen(fname))
  870.       c1 = view_dir(fname);
  871. #endif
  872.  
  873.     if (c1 && (c2 = (access(fname,0)
  874. #if VIEW_HAS_MEMORY
  875.     && stricmp(fname,VIEW_MEM_NAME)
  876. #endif
  877.     ))) 
  878.       {
  879.       strcpy(fname,"File Not Found");
  880.       }
  881.     }
  882.   while(c1 && c2);
  883.  
  884.   if (c1)
  885.     {
  886.     view_new(fname,0,0,16,45);
  887.     return(TRUE);
  888.     }
  889.   else
  890.     return(FALSE);
  891. }
  892. #endif /* VIEW_HAS_NEWFILE */
  893.  
  894. #if VIEW_HAS_SEARCH
  895. int view_search( void )
  896. {
  897.   int c1,c2;
  898.   char pat[80];
  899.   UCHAR *found;
  900.   ULONG pos;
  901.   int ret;
  902.   VIEWFILE *vf;
  903.  
  904.   vf = viewstack->prev->vf;
  905.  
  906.  
  907.   pat[0] = '\0';
  908.  
  909.   do
  910.     {
  911.     c1 = view_prompt("Search","Pattern:",pat,40);
  912.  
  913.     if (c1)
  914.       {
  915.       view_seek(vf,viewstack->prev->pos[0],SEEK_SET);
  916.  
  917.       ret   = 0;
  918.       found = NULL;
  919.  
  920.       while(!ret && !found)
  921.         {
  922.         pos = view_tell(vf);
  923.         ret = view_getl_fwd(vf,view_line,VIEW_MAX_LINE);
  924.         if (!ret) found = strstr(view_line,pat);
  925.         }
  926.  
  927.       if (found)
  928.         {
  929.         view_seek(vf,pos,SEEK_SET);
  930.         viewstack->prev->coff = found-view_line;
  931.         return(TRUE);
  932.         }
  933.       else
  934.         strcpy(pat,"Pattern Not Found");
  935.       }
  936.     }
  937.   while(c1);
  938.  
  939.   return(FALSE);
  940. }
  941. #endif
  942.  
  943.  
  944. #if VIEW_HAS_GOTO
  945. void view_goto_line( void )
  946. {
  947.   int c1;
  948.   char pat[80];
  949.   ULONG pos;
  950.   int ret;
  951.   VIEWFILE *vf;
  952.   UCHAR *goto_pmt[] = {"Offset In File:","Memory Address (SSSSOOOO):","Line Number:"};
  953.   int   goto_len[]  = { 10, 8, 8 };
  954.   int   goto_base[] = { 10,16,10 };
  955.   int   goto_type;
  956.  
  957.   pat[0] = '\0';
  958.   vf = viewstack->prev->vf;
  959.  
  960.  
  961. #if VIEW_HAS_RAW
  962.   if (vf->lmode 
  963.  
  964. #if VIEW_HAS_MEMORY
  965.   && vf->fh != VIEW_MEM_HDL
  966. #endif
  967.  
  968.   )
  969.     goto_type = 0;
  970.  
  971. #if VIEW_HAS_MEMORY
  972.   else if (vf->lmode  && vf->fh == VIEW_MEM_HDL )
  973.     goto_type = 1;
  974. #endif
  975.  
  976.   else
  977. #endif /* VIEW_HAS_RAW */
  978.     goto_type = 2;
  979.  
  980.   c1 = view_prompt("Goto",goto_pmt[goto_type],pat,goto_len[goto_type]);
  981.  
  982.   if (c1)  
  983.     {  
  984.     pos = view_atoul(pat,goto_base[goto_type]);  
  985.  
  986.  
  987.     switch(goto_type)  
  988.       {  
  989. #if VIEW_HAS_RAW
  990.       case 0:  
  991.         view_seek(vf,pos,SEEK_SET);  
  992.       break;  
  993. #endif
  994.  
  995. #if VIEW_HAS_MEMORY
  996.       case 1:  
  997.         view_seek(vf,(ULONG)(((UCHAR _huge *)pos)-memory),SEEK_SET);  
  998.       break;  
  999. #endif
  1000.  
  1001.       case 2:  
  1002.         view_seek(vf,0L,SEEK_SET);  
  1003.  
  1004.         ret = 0;
  1005.         while (!ret && pos)  
  1006.           {  
  1007.           ret = view_getl_fwd(vf,view_line,VIEW_MAX_LINE);  
  1008.           pos --;  
  1009.           }  
  1010.       break;  
  1011.       }  
  1012.     }  
  1013. }
  1014. #endif /* VIEW_HAS_GOTO */
  1015.  
  1016. void _far view_errfunc( void )
  1017.   _hardresume(_HARDERR_FAIL);
  1018. }
  1019.  
  1020. UCHAR *view_strdup( UCHAR *str )
  1021. {
  1022.    str = strdup(str);
  1023.  
  1024.    if (!str)
  1025.      view_error(1,"VIEW0010");
  1026.  
  1027.    return(str);
  1028. }
  1029.